using System;
using System.Collections.Generic;
using System.Linq;
using Engine;
using Game;

namespace RuthlessConquest {
    public class OrderDialog : ListSelectionDialog {
        public const string fName = "RCOrderDialog";

        public class OrderWidget : StackPanelWidget {
            public HumanPlayer Player { get; }
            public Planet TargetPlanet { get; }
            public IEnumerable<Planet> SelectedPlanets { get; }
            public int OrderIndex { get; }
            public LabelWidget Label1 { get; }
            public LabelWidget Label2 { get; }

            public OrderWidget(HumanPlayer player, Planet targetPlanet, IEnumerable<Planet> selectedPlanets, int orderIndex) {
                HorizontalAlignment = WidgetAlignment.Center;
                VerticalAlignment = WidgetAlignment.Center;
                Player = player;
                TargetPlanet = targetPlanet;
                SelectedPlanets = selectedPlanets;
                OrderIndex = orderIndex;
                Direction = LayoutDirection.Vertical;
                Children.Add(Label1 = new LabelWidget { HorizontalAlignment = WidgetAlignment.Center });
                Label2 = new LabelWidget { FontScale = 0.75f, Color = Colors.ForeDisabled, HorizontalAlignment = WidgetAlignment.Center };
                Children.Add(Label2);
            }

            public override void MeasureOverride(Vector2 parentAvailableSize) {
                bool displayOptimalResultOfShipSent = TargetPlanet.Faction == Faction.Neutral || Player.Faction == TargetPlanet.Faction;
                string format = LanguageControl.Get(fName, displayOptimalResultOfShipSent ? "13" : "2");
                int sum = SelectedPlanets.Where(p => p != TargetPlanet).Sum(p => p.ShipsCount);
                switch (OrderIndex) {
                    case 0: {
                        Label1.Text = LanguageControl.Get(fName, "1");
                        if (displayOptimalResultOfShipSent) {
                            int estimated = Math.Min(
                                Player.Faction == TargetPlanet.Faction ? TargetPlanet.ShipsCount + sum :
                                TargetPlanet.ShipsCount > sum * 0.75f ? (int)(TargetPlanet.ShipsCount - sum * 0.75f) :
                                (int)(TargetPlanet.ShipsCount * 1.3333334f - sum),
                                Planet.MaxShipsCapacity
                            );
                            Label2.Text = string.Format(format, sum, $"{TargetPlanet.ShipsCount}→{estimated}");
                        }
                        else {
                            Label2.Text = string.Format(format, sum);
                        }
                        break;
                    }
                    case 1: {
                        Label1.Text = LanguageControl.Get(fName, "3");
                        if (displayOptimalResultOfShipSent) {
                            int estimated = Math.Min(
                                Player.Faction == TargetPlanet.Faction ? TargetPlanet.ShipsCount + sum / 5 :
                                TargetPlanet.ShipsCount > sum * 0.15f ? (int)(TargetPlanet.ShipsCount - sum * 0.15f) :
                                (int)(TargetPlanet.ShipsCount * 0.26666668f - sum * 0.15f),
                                Planet.MaxShipsCapacity
                            );
                            Label2.Text = string.Format(format, sum / 5, $"{TargetPlanet.ShipsCount}→{estimated}");
                        }
                        else {
                            Label2.Text = string.Format(format, sum / 5);
                        }
                        break;
                    }
                    case 2:
                        Label1.Text = LanguageControl.Get(fName, "4");
                        Label2.Text = LanguageControl.Get(fName, "5");
                        break;
                    case 3:
                        Label1.Text = LanguageControl.Get(fName, "6");
                        Label2.Text = LanguageControl.Get(fName, "7");
                        break;
                    case 4:
                        Label1.Text = LanguageControl.Get(fName, TargetPlanet.Satellites.Any() ? "9" : "8");
                        Label1.Color = TargetPlanet.CanLaunchSatellite(false) ? Colors.Fore : Colors.ForeDisabled;
                        Label2.Text = string.Format(LanguageControl.Get(fName, "10"), TargetPlanet.GetSatelliteCost());
                        break;
                }
                base.MeasureOverride(parentAvailableSize);
            }
        }

        public HumanPlayer Player;

        public Planet TargetPlanet;

        public OrderDialog(HumanPlayer player, Planet targetPlanet, IEnumerable<Planet> selectedPlanets) : base(
            LanguageControl.Get(fName, "11"),
            CreateItems(player, targetPlanet, selectedPlanets),
            68f,
            o => new OrderWidget(player, targetPlanet, selectedPlanets, (int)o),
            null
        ) {
            OrderDialog orderDialog = this;
            SelectionColor = global::RuthlessConquest.Player.GetColor(player.Faction);
            Player = player;
            TargetPlanet = targetPlanet;
            ContentSize = new Vector2(420f, 300f);
            SelectionHandler = (Action<object>)Delegate.Combine(
                SelectionHandler,
                (Action<object>)delegate(object o) {
                    switch ((int)o) {
                        case 0: orderDialog.Player.IssueMoveOrder(orderDialog.TargetPlanet, selectedPlanets, 1f, Faction.None); break;
                        case 1: orderDialog.Player.IssueMoveOrder(orderDialog.TargetPlanet, selectedPlanets, 0.2f, Faction.None); break;
                        case 2: orderDialog.Player.IssueContinuousMoveOrder(orderDialog.TargetPlanet, selectedPlanets); break;
                        case 3:
                            DialogsManager.ShowDialog(null, new GiftOrderDialog(orderDialog.Player, orderDialog.TargetPlanet, selectedPlanets));
                            break;
                        case 4:
                            if (targetPlanet.CanLaunchSatellite(false)) {
                                orderDialog.Player.IssueLaunchSatelliteOrder(targetPlanet);
                            }
                            else {
                                player.Game.Screen.MessagesListWidget.AddMessage(
                                    LanguageControl.Get(fName, "12"),
                                    Planet.GetColor(player.Faction),
                                    true
                                );
                            }
                            break;
                    }
                }
            );
        }

        public static IEnumerable<int> CreateItems(HumanPlayer player, Planet targetPlanet, IEnumerable<Planet> selectedPlanets) {
            if (selectedPlanets.Where(p => p != targetPlanet).Count() > 0) {
                yield return 0;
                yield return 1;
                yield return 2;
                if (player.Faction != targetPlanet.Faction) {
                    yield return 3;
                }
            }
            if (player.Faction == targetPlanet.Faction
                && targetPlanet.CanLaunchSatellite(true)) {
                yield return 4;
            }
        }
    }
}